kdl
kdl
is a "document-oriented" parser and API for the KDL Document
Language, a node-based, human-friendly configuration and
serialization format. Unlike serde-based implementations, this crate
preserves formatting when editing, as well as when inserting or changing
values with custom formatting. This is most useful when working with
human-maintained KDL files.
You can think of this crate as
toml_edit
, but for KDL.
If you don't care about formatting or programmatic manipulation, you might
check out knuffel
instead for serde
(or serde-like) parsing.
Example
use KdlDocument;
let doc_str = r#"
hello 1 2 3
world prop="value" {
child 1
child 2
}
"#;
let doc: KdlDocument = doc_str.parse.expect;
assert_eq!;
assert_eq!;
// Documents fully roundtrip:
assert_eq!;
Controlling Formatting
By default, everything is created with default formatting. You can parse items manually to provide custom representations, comments, etc:
let node_str = r#"
// indented comment
"formatted" 1 /* comment */ \
2;
"#;
let mut doc = new;
doc.nodes_mut.push;
assert_eq!;
KdlDocument
, KdlNode
, KdlEntry
, and KdlIdentifier
can all
be parsed and managed this way.
Error Reporting
KdlError
implements miette::Diagnostic
and can be used to display
detailed, pretty-printed diagnostic messages when using miette::Result
and the "fancy"
feature flag for miette
:
# Cargo.toml
[]
= { = "x.y.z", = ["fancy"] }
This will display a message like:
Error:
× Expected valid value.
╭────
1 │ foo 1.
· ─┬
· ╰── invalid float
╰────
help: Floating point numbers must be base 10, and have numbers after the decimal point.
Quirks
Properties
Multiple properties with the same name are allowed, and all duplicated
will be preserved, meaning those documents will correctly round-trip.
When using node.get()
/node["key"]
& company, the last property with
that name's value will be returned.
Numbers
KDL itself does not specify a particular representation for numbers and accepts just about anything valid, no matter how large and how small. This means a few things:
- Numbers without a decimal point are interpreted as u64.
- Numbers with a decimal point are interpreted as f64.
- Floating point numbers that evaluate to f64::INFINITY or f64::NEG_INFINITY or NaN will be represented as such in the values, instead of the original numbers.
- A similar restriction applies to overflowed u64 values.
- The original representation of these numbers will be preserved, unless
you
doc.fmt()
, in which case the original representation will be thrown away and the actual value will be used when serializing.
License
The code in this repository is covered by the Apache-2.0 License.